package main.java.com.chankudo.reflection;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

public class ReflectionMain {
    public static void main(String[] args) {
        try {
            //String clzName = "main.java.com.chankudo.proxy.StaticPersonProxy";
            String clzName = "main.java.com.chankudo.proxy.PersonImpl";

            Class clz = Class.forName(clzName);
            
            System.out.println("analyze fields begin ------>");
            //clz.getDeclaredField(String name);//根据属性的名称获得属性域
            // 这个类下面有哪些属性域 
            //Field[] fields = clz.getFields(); // 返回pulic的属性域
            Field[] fields = clz.getDeclaredFields(); //返回除继承外的所有属性
            for(Field field : fields){
                String fieldName = field.getName();
                System.out.println("filed:"+fieldName);
                
                // 属性域的值的获取和设置
                //field.get(Object obj);从对象中获取到该属性域的取值
                //field.set(obj, value);与上面的方法相对

                // 属性域类型相关
                //Class fieldCls = field.getType();//返回这个属性域的类型，用Class表示。
                //Type fieldType = field.getGenericType();//返回这个属性域的类型，用type表示。

                // 注解相关
                Annotation[] anns = field.getAnnotations(); //获取这个属性的所有注解
                //Annotation ann = field.getAnnotation(Class<T> annotationClass); //获取指定注解类的AnnotatedType对象
                //AnnotatedType annotationType = field.getAnnotatedType();//返回 AnnotatedType 对象，这个对象代表了这个属性域的注解
                //T[] annCls = field.getAnnotationsByType(Class<T> annotationClass); //获取指定注解类的Class[]对象
                // 这些方法与上面相似，区别在于 directly present on this element. This method ignores inherited annotations.
               // Annotation annClz = field.getDeclaredAnnotation(Class<T> annotationClass);
               // field.getDeclaredAnnotations(); 
               // T[] annCls = field.getDeclaredAnnotationsByType(Class<T> annotationClass);
               
               // 返回属性域的修饰符，用int表示。
               // field.getModifiers();
            }
            System.out.println("analyze fields end ------>");

            System.out.println("analyze methods begin ------>");
            // 分析这个类的方法
            Method[] methods = clz.getDeclaredMethods(); //返回除继承的方法以外的所有方法
            //Method[] methods = clz.getMethods(); //返回public方法
            //clz.getMethod(String name, Class... parameterTypes); //用方法名和参数类型来唯一返回一个方法
            //clz.getDeclaredMethod(String name, Class... parameterTypes);
            for(Method method: methods){
                System.out.println("method:"+method.getName());

                // // 方法的参数类型
                // Class[] ParametersCls = method.getParameterTypes();
                // // 返回数据的类型
                // Class returnTypeCls = method.getReturnType();
                // //返回修饰符 int 类型
                // method.getModifiers(); 
                // // 方法抛出的异常的类型
                // Class[] ExpCls = method.getExceptionTypes();

                // 方法的注解相关
                // method.getAnnotations();
                // method.getDeclaredAnnotations();
                // method.getAnnotatedExceptionTypes();
                // method.getAnnotatedParameterTypes();
                // method.getAnnotatedReceiverType();
                // method.getAnnotation(Class<T> annotationClass);
                // method.getAnnotationsByType(Class<T> annotationClass);
                // method.getDeclaredAnnotation(Class<T> annotationClass);
                // method.getDeclaredAnnotationsByType(Class<T> annotationClass);
                
                // 返回这个方法注解中设置的默认值，如果有注解的话。否则返回null
                // Returns the default value for the annotation member represented by this Method
                // method.getDefaultValue()

                // 这些方法返回的都是Type
                // method.getGenericExceptionTypes();
                // method.getAnnotatedParameterTypes();
                // method.getAnnotatedReceiverType();
                // method.getAnnotatedReturnType();
                
                // 参数的一些情况
                // method.getParameterAnnotations();
                // method.getParameterCount();
                // method.getParameterTypes();
                // method.getTypeParameters();

                // 重要 ！！！ 向这个方法传入对象和参数，等同于调用该对象的对应的方法 obj.method(args)
                // 反向代理经常用到
                // method.invoke(obj, args)
            }
            System.out.println("analyze methods end ------>");
            
            System.out.println("analyze Constructor start ------>");
            // 分析这个类的构造方法
            // 根据参数类型获取指定的构造方法
            // clz.getConstructor(Class... parameterTypes);
            Constructor[] constructors = clz.getConstructors();
            for(Constructor constructor: constructors){
                // constructor 向这个构造方法传入参数，返回一个实例。等同于 new 一个实例
                //constructor.newInstance(Object... initargs);

                // 构造方法的参数
                // constructor.getParameterTypes();
                // constructor.getParameterAnnotations();
                // constructor.getParameterTypes();
                // constructor.getTypeParameters();

                // constructor.getModifiers(); // 修饰符

                // constructor.getName();

                // 方法的注解相关
                //constructor.getAnnotations();
                //constructor.getDeclaredAnnotations();
                //constructor.getAnnotatedExceptionTypes();
                //constructor.getAnnotatedParameterTypes();
                //constructor.getAnnotatedReceiverType();
                //constructor.getAnnotation(Class<T> annotationClass);
                //constructor.getAnnotationsByType(Class<T> annotationClass);
                //constructor.getDeclaredAnnotation(Class<T> annotationClass);
                //constructor.getDeclaredAnnotationsByType(Class<T> annotationClass);

                // // 这些方法返回的都是Type
                // constructor.getGenericExceptionTypes();
                // constructor.getAnnotatedParameterTypes();
                // constructor.getAnnotatedReceiverType();
                // constructor.getAnnotatedReturnType();


                // 方法抛出的异常的类型
                //Class[] ExpCls = constructor.getExceptionTypes();
            }
            System.out.println("analyze Constructor end ------>");

            System.out.println("analyze interfaces start ------>");
            //分析这个类的接口
            Class[] interfaces = clz.getInterfaces();
            //Type[] interfacesTypes = clz.getGenericInterfaces();
            //AnnotatedType[] anninterfacesTypes = clz.getAnnotatedInterfaces();
            for (Class itfCls : interfaces) {
                System.out.println("interface:"+itfCls.getName());
            }
            System.out.println("analyze interfaces end ------>");

        } catch (ClassNotFoundException e) {
            System.out.println("class not found.");
            e.printStackTrace();
            return;
        }
    }
    
}
